home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 31
/
Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso
/
Aminet
/
mus
/
midi
/
XGToolset5_src.lha
/
XGToolset_src
/
HowtoProgramSysEx.doc
< prev
next >
Wrap
Text File
|
1999-03-22
|
6KB
|
290 lines
How to programm SYSEX in Bars&Pipes Tools
by Alfred Faust j.k.dax@tonline.de
First: I'm a german man, and I am not so good in the english language
In the "Rules for Tools" manual I found the sentence:
(In the capture :"Events, Clips, & Tracks - Events - 'type'")
"... Only 'EVENT_VOICE' Events flow through the PipeLine; therefore Tools need
only concern themselves with this one type. ... "
That isn't right. 'EVENT_SYSX' Events are also flows through the Pipeline. I
found out how to handle this events, sending directly through the PipeLine and
writing them in the track.
Here is the result of my (guess)work.
First make a string that hold the sysex:
{
char *sysex;
...
sysex = "F07E7F0901F7"; //this is the Geral-MIDI Reset
...
}
or:
{
char *sysex;
storage[16];
...
sprintf(storage, "F07E7F0901F7");
sysex = storage;
...
}
( It is very important that you ALWAYS use STRINGS (char) - not int- or
BYTE-values. You must ALWAYS translate (int or BYTE)-values into (char).
Have a look at the source-codes of my XGTools. There you can also see, how to
put a prop-gadget-value in the SysExString.
One possibility:
{
char *sysex;
storage[16];
int value = 2;
// this can be the value of a slider
char hexstr[3][2]={"00","01","02"};
//that are hexvalues !!!
...
sprintf(storage, "F043104C020102%.2sF7", hexstr[value] );
/*
this is the sysex for REVERB-time in XG-Devices
The "%.2" will be replaced by "02" from hexstr-array,
and then written into storage.
You can also write:
sprintf(storage, "F043104C020102%02lxF7", value)
in this case you don't need the "hexstr"
The "%02lx" will replaced by the value. Always a 2 nibble hexbyte will be
written on this place.
Exapmle:
A value of a slider(Prop-Gadget) is given as decimal "20".
%02lx will be replaced by "14" as hexbyte.
*/
sysex = storage;
... )
For my routines it MUST be a string. Then put it on the way.
These are all functions you need:
//the clip-routines for writing in the track
static BOOL lock_clip(struct Clip *clip) {
Forbid();
if (clip->locked == 0)
{
clip->locked = 1;
Permit();
return TRUE;
}
else
{
Permit();
return FALSE;
} }
static void unlock_clip(struct Clip *clip) {
clip->locked = 0; }
//writes sysex into track
static void insertsysex(char *buff, short size,
struct MNXGTool *tool,const LONG time) {
struct StringEvent *event;
struct String *string;
event = (struct StringEvent *) (*functions->allocevent)();
if (event)
{
string = (struct String *) (*functions->myalloc)(size + 3, MEMF_CLEAR);
if (string)
{
event->next = NULL;
event->string = string;
memcpy(string->string, buff, size);
string->length = size + 2;
event->type = EVENT_SYSX;
event->status = MIDI_SYSX;
event->time = time;
event->tool = tool->tool.next;
if (lock_clip(&(tool->tool.track->clip)))
{
event->next =
(struct StringEvent *)tool->tool.track->clip.events.first;
tool->tool.track->clip.events.first =
(struct Event *)(*functions->sorteventlist)(event);
unlock_clip(&(tool->tool.track->clip));
}
else
{
(*functions->freelist)(event);
}
}
} }
// the routine for sending SysEx-data thru the pipeline
static void sendsysex(char *buff, short size,
struct MNXGTool *tool, const LONG time) {
struct StringEvent *event;
struct String *string;
event = (struct StringEvent *) (*functions->allocevent)();
if (event)
{
string = (struct String *) (*functions->myalloc)(size + 3, MEMF_CLEAR);
if (string)
{
event->string = string;
memcpy(string->string, buff, size);
string->length = size + 2;
event->type = EVENT_SYSX;
event->status = MIDI_SYSX;
event->time = time;
event->tool = tool->tool.next;
WaitTOF();
(*functions->qevent)(event);
(*functions->myfree)(string);
}
} }
// THE MOST IMPORTANT TRANSLATION-ROUTINE
static void trans_hx(struct MNXGTool *tool,
const LONG time, char *sysx, int sw) {
LONG size;
int a, b, x, y ;
UBYTE abuf[32];
char chr[4];
char *zbuf = NULL;
struct Event *sysx_event;
/*
translate sysexbuffer (there are single chars, with his own hexvalue)
into hex (always two chars to one hexvalue)
example: "F0"
In the string there are two hexvalues :
0x46 for "F" in the ASCII-table
0x30 for "0" in the ASCII-table
But we will send the hex-value "0xF0" AND NOT "0x46 0x30"
so we must translate ... */
size = strlen(sysx); zbuf = (char *)AllocVec(size+2, MEMF_ANY|MEMF_CLEAR);
if(zbuf)
{
CopyMem(sysx, zbuf, size);
b=0;
for(a=0;a < size;a=a+2)
{
chr[0] = zbuf[a];
chr[1] = zbuf[a+1];
x=(isdigit((int)chr[0]))? (chr[0]&0xF) : ((chr[0]&0xDF)-55);
y=(isdigit((int)chr[1]))? (chr[1]&0xF) : ((chr[1]&0xDF)-55);
//this is the translationscore - don't touch !!!
abuf[b++] = ((x<<4)|y);
//writing with bitmanipulation
}
FreeVec(zbuf);
if (sw == 0) sendsysex(abuf, b, tool, time);
if (sw == 1) insertsysex(abuf, b, tool, time);
//put hexdata away
} }
There are now to possibilities.
1. Sending through the PipeLine:
{
struct my_Tool *tool;
// a pointer to your Tool-structure
char *sysex;
...
sysex = "F07E7F0901F7";
//this is the Geral-MIDI Reset
trans_hx(tool, functions->timenow, sysex, 0)
// "0" = switch for sending
...
}
If you only need the sendsysex-routine the clip-routines are here not
necessary.
2. Writing in the Track:
{
struct my_Tool *tool;
// a pointer to your Tool-structure
char *sysex;
...
sysex = "F07E7F0901F7"; //this is the Geral-MIDI Reset
if ((*functions->areyousure)("write to track ? Play-pointer on right place?"))
//this is a nice question ...
{
if (!functions->running)
// You CAN'T write into track, if the sequencer is running !!!
{
trans_hx(tool, functions->starttime, sysex, 1)
// "1" = switch for writing
}
}
...
}
If you don't need my comments - kill them ...
I hope my pain, sweat and many sleepless nights are not only useful for my own.